<?php
/**
 * @Author: zhangcc
 * @Date: 2022/8/17
 */

namespace app\libraries\utils\wechat;

use app\libraries\service\table\WxTableService;
use app\libraries\utils\log\LogManager;
use app\libraries\utils\traits\Signleton;
use app\libraries\models\WeixinTableModel;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\ServiceContainer;
use Symfony\Component\HttpFoundation\Request;
use think\facade\Cache;

class EasyWeChatUtil
{
    use Signleton;

    /**
     * 微信APP类型
     *
     * @var array
     * @Author YangHB
     * @DateTime 2022-07-27 16:15:35
     *
     */
    protected array $wxAppType = [
        0 => 'officialAccount',
        1 => 'miniProgram',
        2 => 'payment',
        3 => 'openPlatform',
        4 => 'work',
        6 => 'openWork',
        7 => 'microMerchant',
        8 => 'basicService',
    ];

    /**
     * 配置信息
     *
     * @var array
     * @Author YangHB
     * @DateTime 2022-07-27 16:49:39
     *
     */
    protected array $options = [
        'app_id' => '',
        'secret' => '',
        'token' => '',
        'log' => [
            'default' => 'channel',
            'channels' => [
                'channel' => [
                    'driver' => 'single',
                    'path' => '',
                    'level' => 'debug',
                    'permission' => 0777,
                ],
            ],
        ],
    ];

    /**
     * 缓存初始化好的应用信息
     *
     * @var ServiceContainer[]
     * @Author YangHB
     * @DateTime 2021-11-09 23:38:24
     *
     */
    protected array $guidAppList = [];

    /**
     * 返回微信公众号初始应用
     * @param WeixinTableModel $wxItem
     * @return ServiceContainer
     */
    public function initAccountApp(WeixinTableModel $wxItem): ServiceContainer
    {
        //如果已经在进程内生成过了，直接返回
        if (!empty($this->guidAppList[$wxItem->guid])) {
            return $this->guidAppList[$wxItem->guid];
        }
        $option = $this->options;
        $option['log']['channels']['channel']['path'] = (config('log.log_file_path') ?? runtime_path('wechat')) .
            date('Ymd') . '_wechat' . '.log';
        $option['log']['channels']['channel']['level'] = config('wechat.log_level');
        $option['app_id'] = $wxItem->wxAppId;
        $option['secret'] = $wxItem->wxAppSecret;
        $option['token'] = $wxItem->wxToken;
        $option['aes_key'] = $wxItem->wxEncodeKey;
        $option['mch_id'] = $wxItem->payMchId;
        $option['key'] = $wxItem->payKey;
        // 重写http配置
        $option['http'] = [
            'timeout' => 30.0,
            'base_uri' => 'https://api.weixin.qq.com/',
            'verify' => false, // ssl 请求不验证证书
        ];
        $appType = $this->wxAppType[$wxItem->wxType];

        $wxApp = Factory::make($appType, $option);
        $wxApp['cache'] = Cache::store('wechat_redis');
        /* 支持对接
        if (!$app->isDebug()) {
            $wxApp->server->forceValidate();
        }
        */
        $wxApp->rebind('logger', new LogManager($wxApp));
        $wxApp->rebind('log', $wxApp['logger']);
        $wxApp->rebind('access_token', new AccessToken($wxApp));
        $wxRequest = new Request(
            app()->request->get(),
            app()->request->post(),
            [],
            app()->request->cookie(),
            app()->request->file() ?? [],
            app()->request->server(),
            app()->request->getContent()
        );
        $wxApp->rebind('request', $wxRequest);
        app()->bind(get_class($wxApp), $wxApp);
        $this->guidAppList[$wxItem->guid] = $wxApp;
        return $this->guidAppList[$wxItem->guid];
    }
}